package com.nineclock.attendance.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.nineclock.attendance.config.PunchUtils;
import com.nineclock.attendance.dto.AttendGroupDTO;
import com.nineclock.attendance.dto.AttendPunchDTO;
import com.nineclock.attendance.mapper.AttendPunchMapper;
import com.nineclock.attendance.pojo.AttendPunch;
import com.nineclock.attendance.service.AttendGroupService;
import com.nineclock.attendance.service.AttendPunchService;
import com.nineclock.common.enums.ResponseEnum;
import com.nineclock.common.exception.NcException;
import com.nineclock.common.threadLocal.CurrentUserHolder;
import com.nineclock.common.utils.BeanHelper;
import com.nineclock.common.utils.DateTimeUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Currency;
import java.util.Date;

@Slf4j
@Service
public class AttendPunchServiceImpl implements AttendPunchService {

    /**
     * 移动端":打卡
     */
    @Autowired
    private AttendPunchMapper attendPunchMapper;

    @Autowired
    private AttendGroupService attendGroupService;

    @Override
    public void punch(AttendPunchDTO attendPunchDTO) {
        //健壮性判断
        if (attendPunchDTO == null) {
            throw new NcException(ResponseEnum.USER_NOT_JOIN_COMPANY);
        }
        //获取考勤组信息
        AttendGroupDTO attendGroupDTO = attendGroupService.getAttendGroupByUserId();

        //数据转化
        AttendPunch attendPunch = BeanHelper.copyProperties(attendPunchDTO, AttendPunch.class);
        attendPunch.setCompanyId(CurrentUserHolder.get().getCompanyId());//企业idattendPunch = {AttendPunch@15057} "AttendPunch(id=null, companyUserId=1, companyId=1, lat=null, lng=null, address=null, punchTime=Tue Aug 17 23:32:54 CST 2021, punchDateStr=2021-08-17, morningPunchType=null, afternoonPunchType=1, areaValid=null, effectiveValid=true, punchOnOffWork=2, dayType=null, punchSource=null, makeupStatus=null, makeupReason=null, makeupApproveUserId=null, makeupApproveTime=null, createTime=Tue Aug 17 23:32:54 CST 2021)"
        attendPunch.setCompanyUserId(CurrentUserHolder.get().getCompanyUserId()); //用户id
        attendPunch.setLat((attendPunchDTO.getLat())); //设置经度
        attendPunch.setLng(attendPunchDTO.getLng()); //设置纬度
        attendPunch.setPunchTime(new Date());//打卡时间
        attendPunch.setCreateTime(new Date());//创建时间
        //通过DateTimeUtil工具类提供的时间转成字符串
        attendPunch.setPunchDateStr(DateTimeUtil.dateToStr(new Date(), "yyyy-MM-dd"));//打卡日期

        /**
         * 通过DateTimeUtil工具类中noonType方法来判断是是上午还是下午
         * 上午返回 0 ,下午返回 1
         * */

        attendPunch.setPunchOnOffWork(DateTimeUtil.noonType(new Date()) + 1);//是上午打卡还是下午打卡

        /**校验是是否工作日打卡*/
        boolean validateWorkDay = PunchUtils.validateWorkDay(attendGroupDTO);
        if(!validateWorkDay){
            throw new NcException(ResponseEnum.PUNCH_INVALID_DAY);
        }

        /**
         * 1. 查询打卡记录，如果没有查询到，无论何时打卡都是有效的
         * 2. 查询到了
         * 如果是上午打卡， 则无效
         * 如果是下午打卡， 以最后一次打卡记录为准, 之前打卡记录无效
         */
        boolean validatePunch = this.validatePunch(attendPunch);
        if (validatePunch){
            /**
             * 判断是否有效是有效打卡,如果有效通过PunchUtils工具类来设置打卡类型
             * */
            PunchUtils.setPunchType(attendPunch,attendGroupDTO);
        }

        /**
         * 通过打卡工具类来判断打卡范围是否符合规则
         * */
        System.out.println(attendPunchDTO);
        boolean flag = PunchUtils.validatePunchArea(attendPunchDTO, attendGroupDTO);
        attendPunch.setAreaValid(flag);
        if (!flag){
            throw new NcException(ResponseEnum.PUNCH_INVALID_AREA);
        }

        //保存数据
        attendPunchMapper.insert(attendPunch);
    }

    /**
     * 1. 查询打卡记录，如果没有查询到，无论何时打卡都是有效的
     * 2. 查询到了
     * 如果是上午打卡， 则无效
     * 如果是下午打卡， 以最后一次打卡记录为准, 之前打卡记录无效
     *
     * @param attendPunch
     * @return
     */
    private boolean validatePunch(AttendPunch attendPunch) {
        LambdaQueryWrapper<AttendPunch> punchQw = new LambdaQueryWrapper<>();

        punchQw.eq(AttendPunch::getPunchOnOffWork, attendPunch.getPunchOnOffWork());
        punchQw.eq(AttendPunch::getCompanyId, CurrentUserHolder.get().getCompanyId());
        punchQw.eq(AttendPunch::getCompanyUserId, CurrentUserHolder.get().getCompanyUserId());
        punchQw.eq(AttendPunch::getPunchDateStr, attendPunch.getPunchDateStr());

        Integer count = attendPunchMapper.selectCount(punchQw);

        if (count == 0) {
            attendPunch.setEffectiveValid(true);
        } else {
            if (attendPunch.getPunchOnOffWork() == 1) {
                attendPunch.setEffectiveValid(false);
            } else {
                attendPunch.setEffectiveValid(true);

                AttendPunch updateAttendPunch = new AttendPunch();
                updateAttendPunch.setEffectiveValid(false);
                attendPunchMapper.update(updateAttendPunch, punchQw);
            }
        }
        return attendPunch.getEffectiveValid();
    }
}
